#include "WinMain.h"	// standard application include
#include "Utility.h"	// application-independent utility functions

///////////////////////////////////////////////////////////////////////////////////////////////////

/*/
/ / bool
/ /		CenterWnd (HWND hwnd, HWND hwndPreferred)
/ /
/ / PURPOSE:
/ /		Function to center a window, either in correspondence
/ /		with a preferred window, a parent window, or the work area.
/ /
/ /	CREDITS:
/ /		This function originated as the CenterWindow function found in the
/ /		book "Win32 Programming" by Brent E. Rector and Joseph M. Newcomer.
/ /		I, Jeremy Falcon, modified it to compile cleanly under warning level
/ /		4 and to gain a slight performance increase under certain conditions.
/*/

bool
CenterWnd (HWND hwnd, HWND hwndPreferred)
{
	bool	bResult = false;
	POINT	PreferredPoint = {0}, CenteredPoint = {0};
	RECT	WndRect = {0}, PreferredRect = {0}, WorkArea = {0};
	SIZE	CenteredWnd = {0};

	if((hwnd != NULL) && IsWindow(hwnd))
	{
		/*/ See if a preferred window is specified /*/
		if(NULL == hwndPreferred)
			/*/ See if window to be centered is a child /*/
			hwndPreferred = GetWindowOwner(hwnd);

		/*/ Center around the preferred window if exists; otherwise, center in the work area /*/
		if(NULL != hwndPreferred)
		{
			if(!IsWindow(hwndPreferred)) return false;
			GetWindowRect(hwndPreferred, &PreferredRect);
		}
		else
		{
			/*/ Get the rectangle for the work area /*/
			bResult = SystemParametersInfo(SPI_GETWORKAREA, sizeof(RECT), &WorkArea, 0);

			/*/
			/ / If the above call failed Explorer is not running correctly;
			/ / therefore, there is no work area (and taskbar). So, we'll
			/ / use the screen size instead for our coordinates.
			/*/

			if(!bResult)
			{
				SetRect(&WorkArea, 0, 0, 
						GetSystemMetrics (SM_CXSCREEN),
						GetSystemMetrics (SM_CYSCREEN));
			}

			PreferredRect = WorkArea;
		}

		/*/ Preferred center point /*/
		PreferredPoint.x = (PreferredRect.left + PreferredRect.right)  / 2;
		PreferredPoint.y = (PreferredRect.top  + PreferredRect.bottom) / 2;

		/*/ Get the window's (to be centered) rectangle and compute the width/height /*/
		GetWindowRect(hwnd, &WndRect);
		CenteredWnd.cx = (WndRect.right  - WndRect.left);
		CenteredWnd.cy = (WndRect.bottom - WndRect.top);

		/*/ Center window in preferred horizontally (left side) /*/
		CenteredPoint.x = PreferredPoint.x - (CenteredWnd.cx / 2);

		/*/ Center window in owner vertically (top side) /*/
		CenteredPoint.y = PreferredPoint.y - (CenteredWnd.cy / 2);

		/*/
		/ / If the left edge of the centered window is clipped by the work area
		/ / move the window to the right until the edge is exposed.
		/*/
		if(CenteredPoint.x < WorkArea.left) CenteredPoint.x = WorkArea.left;

		/*/
		/ / If the right edge of the centered window is clipped by the work area
		/ / move the window to the left until the edge is exposed.
		/*/
		else if(CenteredPoint.x + CenteredWnd.cx > WorkArea.right)
			CenteredPoint.x = (WorkArea.right - CenteredWnd.cx);

		/*/
		/ / If the top edge of the centered window is clipped by the work area
		/ / move the window down until the edge is exposed.
		/*/
		if (CenteredPoint.y < WorkArea.top) CenteredPoint.y = WorkArea.top;

		/*/
		/ / If the bottom edge of the centered window is clipped by the work area
		/ / move the window up until the edge is exposed.
		/*/
		else if (CenteredPoint.y + CenteredWnd.cy > WorkArea.bottom)
			CenteredPoint.y = (WorkArea.bottom - CenteredWnd.cy);

		/*/ Reposition the centered window /*/
		bResult = SetWindowPos(hwnd, NULL, CenteredPoint.x, CenteredPoint.y,
								0, 0, SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
	}

	return bResult;
}

///////////////////////////////////////////////////////////////////////////////////////////////////

/*/
/ / unsigned int
/ /		SafeTexSize (const unsigned int nSize)
/ /
/ /		nSize = size/dimension you wish to test
/ /
/ / PURPOSE:
/ /		Returns a safe texture size to use (a power of 2) based
/ /		on the size that's passed. This is a convenience function.
/*/

unsigned int
SafeTexSize (const unsigned int nSize)
{
	unsigned int nShift = 0, nAmount = 0, nReturn = 0;

	// for POT we'll shift bits along until size in bits minus one (8 bits per byte)
	nAmount = sizeof(nSize) * 8 - 1;

	// a safe size will be a POT size, yes OGL 2.0 and GL_ARB_texture_non_power_of_two
	// allow for a NPOT texture size, but performance is still greater with POT
	for(nShift = 0; nShift < nAmount; nShift++)
	{
		nReturn = (unsigned int)(1 << nShift);
		if(nSize <= nReturn) break;
	}

	return nReturn;
}

///////////////////////////////////////////////////////////////////////////////////////////////////

/*/
/ / bool
/ /		IsLittleEndian (void)
/ /
/ / PURPOSE:
/ /		Test the endianess of the machine (for poartability reasons).
/*/

bool
IsLittleEndian (void)
{
	unsigned __int16 x = 1;				// make sure variable is more than one byte
	const char *p = (const char *)&x;	// make sure variable is only one byte

	// note: in little endian the lower address will contain the least significant byte
	return (p[0] == 1) ? true : false;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////